#include <iostream>
#include <thread>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>

#define BUFFER_SIZE 1024

void receive_messages(int sock) {
    char buffer[BUFFER_SIZE];
    while (true) {
        int bytes_received = recv(sock, buffer, BUFFER_SIZE, 0);
        if (bytes_received <= 0) {
            std::cout << "Connection closed by server." << std::endl;
            break;
        }
        buffer[bytes_received] = '\0';
        std::cout << "\nReceived: " << buffer << std::endl;
    }
}

void send_messages(int sock) {
    char buffer[BUFFER_SIZE];
    while (true) {
        std::cout << "Enter message: \n";
        std::cin.getline(buffer, BUFFER_SIZE);
        send(sock, buffer, strlen(buffer), 0);
    }
}

int main(int argc, char* argv[]) {
    if (argc != 4) {
        std::cout << "Usage: " << argv[0] << " <local_ip> <server_ip> <port>" << std::endl;
        return 1;
    }

    const char* local_ip = argv[1];
    const char* server_ip = argv[2];
    int port = atoi(argv[3]);
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in local_addr, server_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = inet_addr(local_ip);
    local_addr.sin_port = htons(0);

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(server_ip);
    server_addr.sin_port = htons(port);

    bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr));
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 客户端里就不用detach啦，所以可以用join来保持和子线程之间的联系。
    std::thread receiver(receive_messages, sock);
    std::thread sender(send_messages, sock);
    receiver.join();
    sender.join();

    close(sock);
    return 0;
}

